#include <iostream>
#include <pthread.h>
#include <string> 
#include <unistd.h>

class TD
{
public:
    TD(pthread_mutex_t* mtx,pthread_cond_t* cond,const std::string& name):_mtx(mtx),_cond(cond),_name(name){}
    pthread_mutex_t *_mtx; 
    pthread_cond_t* _cond; 
    std::string _name;
};

void *Con(void* args)
{
    TD* td = (TD*)args;
    while(1)
    {
        pthread_mutex_lock(td->_mtx);
        std::cout << td->_name << "begin wait..... " << std::endl; 
        pthread_cond_wait(td->_cond,td->_mtx);
        std::cout << td->_name << "wait over....."  <<  std::endl; 
        pthread_mutex_unlock(td->_mtx);
    }
}


void *Prod(void* args)
{
    TD* td = (TD*)args;
    while(1)
    {
        pthread_mutex_lock(td->_mtx);
        std::cout << td->_name << "start to send singal..... " << std::endl; 
        pthread_cond_signal(td->_cond);
        std::cout << td->_name << "singal already is sent....."  <<  std::endl; 
        int cnt = 5;
        while(cnt--)
        {
            sleep(1);
            std::cout << "cnt : " << cnt << "   if cnt = 0 unlock is called" << std::endl;
        }
        pthread_mutex_unlock(td->_mtx);
        sleep(3); 
    }
}



int main()
{
    pthread_t tid1,tid2,tid3,tid4; 
    pthread_mutex_t mutex; 
    pthread_cond_t cond; 
    pthread_mutex_init(&mutex,nullptr); 
    pthread_cond_init(&cond,nullptr);
    TD* td1 = new TD(&mutex,&cond,"td1 ");
    TD* td2 = new TD(&mutex,&cond,"send signal thread ");
    TD* td3 = new TD(&mutex,&cond,"td3 ");
    TD* td4 = new TD(&mutex,&cond, "td4 ");
    pthread_create(&tid1,nullptr,Con,(void*)td1); 
    pthread_create(&tid2,nullptr,Prod,(void*)td2); 
    pthread_create(&tid3,nullptr,Con,(void*)td3); 
    pthread_create(&tid4,nullptr,Con,(void*)td4); 

    

    pthread_join(tid1,nullptr);
    pthread_join(tid2,nullptr);
    pthread_join(tid3,nullptr);
    pthread_join(tid4,nullptr);


    return 0 ;
}